免费的云数据库有很多,我使用prisma官方的postgresql和它的加速功能,数据库有1G的容量,访问次数10万/月,非常够用了。

还有很多postgresql数据库,比如neon、Supabase等等,这些数据库使用的时候,如果项目代码中使用了prisma,注意要结合prisma accelerate一起使用,速度会更快。
model里面,我将model Words 改为 model Word之后,使用this.prisma.word会报错。
解决办法,将generated文件夹删除掉,然后运行npx prisma generate重新生成。然后把vscode重启,就好了。
这就给出了一个通用的解决办法,就是model里面无论改变了什么,都使用上面的方法来解决。
在prisma 7中,Prisma Client 现在默认生成 ES 模块 (ESM) 代码。即使生成的源文件后缀是 .ts,为了遵循 Node.js 的 ESM 规范,它内部的 import 路径必须显式包含 .js 后缀。
这在 NestJS(通常使用 Webpack 或 CommonJS)中会造成路径无法解析的错误。
现象是:在client.ts文件中,引入了internal文件夹里面的一些文件,这些文件都是 .ts 后缀。但是引入的代码,写的却是.js后缀,那么在引用client的时候,就会报错。
解决办法:
Prisma 允许你配置生成文件的后缀和导入后缀。将以下配置添加到你的 generator client 块中:
1generator client {2 provider = "prisma-client"3 output = "../generated/prisma"4 // 强制生成的导入使用 .ts 结尾,而不是 .js5 importFileExtension = "ts"6}添加后,重新运行 npx prisma generate。这样生成的代码中,所有的 import ... from './internal/xxx.js' 都会变成 ./internal/xxx.ts。
参考:https://www.youtube.com/watch?v=XHYAYe-nmxg&t=51s
如果还是解决不了,那要么使用prisma v6,要么升级到最新的prisma版本,看他们修复了没有。
在列表查询中,除了page和limit这两个参数之外,还有很多搜索相关的参数,这些参数传递过来的时候,应该怎么写where条件呢?
在使用 Prisma 进行列表查询时,当有大量可选的搜索/过滤参数时,最推荐的做法是:
where 对象假设我们有一个用户列表查询接口,支持以下搜索/过滤条件:
x1import { Prisma } from '@prisma/client';23// 类型定义(建议抽离出来,方便复用)4interface UserListQueryParams {5 page?: number;6 limit?: number;7 search?: string; // 关键字搜索8 gender?: 'male' | 'female' | 'other' | string;9 minAge?: number;10 maxAge?: number;11 startDate?: string; // ISO 格式日期字符串12 endDate?: string;13 status?: 'active' | 'inactive' | 'banned';14 roles?: string[]; // 多选角色 ['admin', 'user']15 isPremium?: boolean;16 sortBy?: 'createdAt' | 'lastLoginAt' | 'name';17 sortOrder?: 'asc' | 'desc';18}1920// 构建 where 条件的函数(核心部分)21function buildUserWhere(params: UserListQueryParams): Prisma.UserWhereInput {22 const where: Prisma.UserWhereInput = {};2324 // 1. 关键字搜索(用户名、邮箱、昵称任意一个匹配)25 if (params.search?.trim()) {26 const searchTerm = params.search.trim();27 where.OR = [28 { username: { contains: searchTerm, mode: 'insensitive' } },// mode: 'insensitive' 表示“不区分大小写的查询”29 { email: { contains: searchTerm, mode: 'insensitive' } },30 { nickname: { contains: searchTerm, mode: 'insensitive' } },31 ];32 }3334 // 2. 性别(精确匹配)35 if (params.gender && ['male', 'female', 'other'].includes(params.gender)) {36 where.gender = params.gender as 'male' | 'female' | 'other';37 }3839 // 3. 年龄范围(基于 birthDate 计算)40 if (params.minAge || params.maxAge) {41 const today = new Date();42 const minBirth = params.minAge43 ? new Date(today.getFullYear() - params.minAge, today.getMonth(), today.getDate())44 : undefined;45 const maxBirth = params.maxAge46 ? new Date(today.getFullYear() - params.maxAge - 1, today.getMonth(), today.getDate() + 1)47 : undefined;4849 where.birthDate = {50 (minBirth && { gte: minBirth }),51 (maxBirth && { lte: maxBirth }),52 };53 }5455 // 4. 注册时间范围56 if (params.startDate || params.endDate) {57 where.createdAt = {58 (params.startDate && { gte: new Date(params.startDate) }),59 (params.endDate && { lte: new Date(params.endDate) }),60 };61 }6263 // 5. 状态64 if (params.status) {65 where.status = params.status;66 }6768 // 6. 角色(多选,包含任意一个即可)69 if (params.roles?.length) {70 where.roles = {71 hasSome: params.roles,72 };73 }7475 // 7. 是否付费用户76 if (params.isPremium !== undefined) {77 where.isPremium = params.isPremium;78 }7980 return where;81}8283// 主查询函数示例84export async function getUserList(params: UserListQueryParams) {85 const page = Math.max(1, params.page ?? 1);86 const limit = Math.min(100, Math.max(1, params.limit ?? 20)); // 防止滥用87 const skip = (page - 1) * limit;8889 const where = buildUserWhere(params);9091 // 可选:排序92 const orderBy: Prisma.UserOrderByWithRelationInput[] = [];93 if (params.sortBy) {94 orderBy.push({95 [params.sortBy]: params.sortOrder ?? 'desc',96 });97 } else {98 orderBy.push({ createdAt: 'desc' }); // 默认排序99 }100101 const [users, total] = await Promise.all([102 prisma.user.findMany({103 where,104 orderBy,105 skip,106 take: limit,107 select: {108 id: true,109 username: true,110 email: true,111 nickname: true,112 gender: true,113 birthDate: true,114 createdAt: true,115 status: true,116 roles: true,117 isPremium: true,118 },119 }),120 prisma.user.count({ where }),121 ]);122123 return {124 data: users,125 pagination: {126 total,127 page,128 limit,129 totalPages: Math.ceil(total / limit),130 },131 };132}那么假设所有搜索条件都加上了,最终的where会是什么样的呢?
xxxxxxxxxx271const where: Prisma.UserWhereInput = {2 OR: [3 { username: { contains: "tom", mode: "insensitive" } },4 { email: { contains: "tom", mode: "insensitive" } },5 { nickname: { contains: "tom", mode: "insensitive" } },6 ],78 gender: "male",910 birthDate: {11 gte: new Date("2008-01-17"), // 假设当前日期 ≈ 2026-01-17,minAge=1812 lte: new Date("1990-01-17"), // maxAge=35 → 出生日期上限 ≈ 1990-01-1713 },1415 createdAt: {16 gte: new Date("2024-01-01T00:00:00.000Z"),17 lte: new Date("2025-12-31T23:59:59.999Z"),18 },1920 status: "active",2122 roles: {23 hasSome: ["admin", "moderator"],24 },2526 isPremium: true,27};总结一下:
先将where定义成空对象{},然后如果是模糊搜索(在同一个输入框中,可以输入邮箱或者用户名或者userId来搜索),就使用where.OR = [{字段名: {contains: params.search, mode: 'insensitive'}}, ...更多字段名]来处理;如果是精确搜索,那么使用where.xxx = params.xxx加上去即可。